package com.association.interceptor;

import com.alibaba.fastjson.JSON;
import com.association.constant.CodeEnum;
import com.association.constant.Global;
import com.association.model.DistrictResp;
import com.association.model.ResultResp;
import com.github.pagehelper.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
 * 请求参数校验
 * Created by keyong on 2020/4/24/024.
 */
@Slf4j
@Aspect
@Component
public class ValidatorInterceptor {

    @Pointcut("execution(* com.association.controller.*.*(..))")
    public void pointcut() {}

    @Around("pointcut()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Exception {
        try {
            Object[] args = joinPoint.getArgs();
            String errorMessage = validator(args);
            if (!StringUtil.isEmpty(errorMessage)) {
                returnResp(CodeEnum.INVALID, errorMessage);
                return null;
            }
            return joinPoint.proceed();
        } catch (Throwable t) {
            t.printStackTrace();
            log.error("execute error, cause:{}", t.getMessage());
            returnResp(CodeEnum.SERVER, CodeEnum.SERVER.getMessage());
            return null;
        }
    }

    /**
     * 请求参数校验有效性
     * @param args
     * @return
     * @throws IOException
     */
    private String validator(Object[] args) {
        for (Object arg : args) {
            if (arg instanceof BindingResult) {
                BindingResult bindingResult = (BindingResult) arg;
                if (bindingResult.hasErrors()) {
                    List<ObjectError> allErrors = bindingResult.getAllErrors();
                    return allErrors.get(0).getDefaultMessage();
                }
                break;
            }
        }
        return null;
    }

    private void returnResp(CodeEnum codeEnum, String errorMessage) throws IOException {
        ResultResp result = new DistrictResp(codeEnum, errorMessage);
        returnResp(result);
    }

    private void returnResp(ResultResp result) throws IOException {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = attributes.getResponse();
        response.setCharacterEncoding(Global.DEFAULT_ENCODING);
        response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
        PrintWriter writer = response.getWriter();
        writer.write(JSON.toJSONString(result));
    }
}
